home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / lib / ftw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-04  |  2.6 KB  |  111 lines

  1.  
  2. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  3.  
  4. /*
  5. **  FTW
  6. **  Walk a directory hierarchy from a given point, calling a user-supplied
  7. **  function at each thing we find.  If we go below a specified depth,
  8. **  recycle file descriptors.
  9. */
  10.  
  11. #include <stdio.h>
  12. /* #include <sys/types.h> */
  13. #include "../ir/cdialect.h"
  14. #include <sys/stat.h>
  15. #include "pdftw.h"
  16.  
  17. #ifdef    RCSID
  18. static char RCS[] = "$Header: /usr/local/ls6/src+data/src/freeWAIS-sf/lib/RCS/ftw.c,v 1.1 1994/08/05 07:13:36 pfeifer Exp $";
  19. #endif    /* RCSID */
  20.  
  21. #define EQ(a, b)    (strcmp((a), (b)) == 0)
  22.  
  23. /*
  24. extern char        *malloc();
  25. extern char        *strcpy();
  26. */
  27. int
  28. ftw(directory, funcptr, depth)
  29.     char         *directory;
  30.     int            (*funcptr)();
  31.     int              depth;
  32. {
  33.     register DIR     *dirp;
  34.     struct dirent         *entp;
  35.     struct stat          stats;
  36.     register char     *p;
  37.     register int      i;
  38.     long          seekpoint;
  39.     char         *fullpath;
  40.  
  41.     /* If can't stat, tell the user so. */
  42.     if (stat(directory, &stats) < 0)
  43.     return (*funcptr)(directory, &stats, FTW_NS);
  44.  
  45.     /* If it's not a directory, call the user's function. */
  46.     if ((stats.st_mode & S_IFMT) != S_IFDIR)
  47.     /* Saying "FTW_F" here is lying; what if this is a symlink? */
  48.     return (*funcptr)(directory, &stats, FTW_F);
  49.  
  50.     /* Open directory; if we can't, tell the user so. */
  51.     dirp = opendir(directory);
  52.     if (dirp == NULL)
  53.     return (*funcptr)(directory, &stats, FTW_DNR);
  54.  
  55.     /* See if user wants to go further. */
  56.     i = (*funcptr)(directory, &stats, FTW_D);
  57.     if (i) {
  58.     closedir(dirp);
  59.     return i;
  60.     }
  61.  
  62.     /* Get ready to hold the full paths. */
  63.     i = strlen(directory);
  64.     fullpath = (char *)malloc(i + 1 + MAXNAMLEN + 1);
  65.     if (fullpath == NULL) {
  66.     closedir(dirp);
  67.     return -1;
  68.     }
  69.     (void)strcpy(fullpath, directory);
  70.     p = &fullpath[i];
  71.     if (i && p[-1] != '/')
  72.     *p++ = '/';
  73.  
  74.     /* Read all entries in the directory.. */
  75.     while (entp = readdir(dirp))
  76.     if (!EQ(entp->d_name, ".") && !EQ(entp->d_name, "..")) {
  77.         if (depth <= 1) {
  78.         /* Going too deep; checkpoint and close this directory. */
  79.         seekpoint = telldir(dirp);
  80.         closedir(dirp);
  81.         dirp = NULL;
  82.         }
  83.  
  84.         /* Process the file. */
  85.         (void)strcpy(p, entp->d_name);
  86.         i = ftw(fullpath, funcptr, depth - 1);
  87.         if (i) {
  88.         /* User's finished; clean up. */
  89.         free(fullpath);
  90.         if (dirp)
  91.             closedir(dirp);
  92.         return i;
  93.         }
  94.  
  95.         /* Reopen the directory if necessary. */
  96.         if (dirp == NULL) {
  97.         dirp = opendir(directory);
  98.         if (dirp == NULL) {
  99.             free(fullpath);
  100.             return -1;
  101.         }
  102.         seekdir(dirp, seekpoint);
  103.         }
  104.     }
  105.  
  106.     /* Clean up. */
  107.     free(fullpath);
  108.     closedir(dirp);
  109.     return 0;
  110. }
  111.